
/** 默认头信息 */
const DEFAULT_HEAD = {
    'Content-Type': 'application/json',
    'Accept-Charset': 'utf-8',
    /** 为解决跨域问题 */
    'Origin': '*'
};

type HTTPRequestMethod = "CONNECT"| "DELETE"| "GET"| "HEAD"| "OPTIONS"| "PATCH"| "POST"| "PUT"| "TRACE";

const HREQM: {[key in HTTPRequestMethod]: string} = {
	CONNECT: 'lightslategray',
	HEAD: 'cadetblue',
	OPTIONS: 'thistle',
	GET: 'lightgreen',
	PUT: 'darkcyan',
	DELETE: 'lightcoral',
	POST: 'deepskyblue',
	PATCH: 'silver',
	TRACE: 'steelblue',
}

/**
 * 创建请求头
 * @param conf
 */
function createHeader(conf?: {[field: string]: string}){
	let header = new Headers();
	[DEFAULT_HEAD, conf].forEach(list=>{
		if(!list) return void 0;
		for(let field in list) header.append(field, Reflect.get(list, field));
	});
	return header;
}

/**
 * 格式化请求数据
 * @param param 请求数据
 * @param type 格式类型
 */
function FormateData(param: {[name: string]: string|number}, type: 'json'|'form'|'search'){
    let data: string | FormData;
    if(type==='json') data = JSON.stringify(param);
    else if(type==='search'){
        let arr = [];
        for(let name in param) arr.push(`${name}=${param[name]}`);
        data = arr.join('&');
    }else if(type==='form'){
        data = new FormData();
        for(let name in param) data.set(name, String(param[name]));
    }

    return data;
}

/**
 * 创建一个请求对象
 * @param url 请求路径
 * @param data 请求参数
 * @param method 请求方法类型
 * @param head 请求头配置
 */
function createRequest(url: string, data: any, method?: HTTPRequestMethod, head?: {[name: string]: string}){

    let body = FormateData(data, 'json');
	let options: RequestInit = {
		method: method??"GET",
		headers: createHeader(head)
	}

	if(options.method=='POST') options.body = body;

    let request = new Request(url, options);

    return request;
}

/** 向服务器发送请求 */
export async function http_send(...args: Parameters<typeof createRequest>){
	args[2] = args[2] ?? 'GET';

	mtec.log.tag([
		['SERVICE', 'slategray'],
		[args[2], Reflect.get(HREQM, args[2])],
		['>>', 'dodgerblue']
	].map(_=>_.join(':')).join(';'), args[0].split('/').slice(3).join('/'), '\n--------------\nHEADERS:', args[3], '\nDATA:', args[1], '\n--------------\n');

	let start_stamp = Date.now();
	let response = await fetch(createRequest(...args))
	.then(res=>res)
	.catch(err=>{
		mtec.log.warn(err);
		throw '请求失败';
	});
	let delay = Date.now() - start_stamp;

	let data = response.ok ? await response.json() : undefined;

	mtec.log.tag([
		['SERVICE', 'slategray'],
		[args[2], Reflect.get(HREQM, args[2])],
		['<<', 'seagreen'],
		data ? ['OK', 'springgreen'] : ['ERR', 'red'],
		[delay + ' ms', 'silver']
	].map(_=>_.join(':')).join(';'), args[0].split('/').slice(3).join('/'), '\n--------------\nRESPONSE:', response, '\nDATA:', data, '\n--------------\n');

	return data;
}